// XframeWork.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
//#include <vld.h>
#include "XframeWork.h"
#include "XMain.h"
#include "tinyxml/tinyxml.h"



#ifndef GET_X_LPARAM
#define GET_X_LPARAM(lp)                        ((int)(short)LOWORD(lp))
#endif
#ifndef GET_Y_LPARAM
#define GET_Y_LPARAM(lp)                        ((int)(short)HIWORD(lp))
#endif



#define MAX_LOADSTRING 100


HWND g_hWnd=NULL;

static XE::xVector2 oldpos(0.0f,0.0f);
// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name



void Render()
{
	XE::XEngine::getSingletonPtr()->Render();
	return ;
};



// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	// TODO: Place code here.

	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_XFRAMEWORK, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_XFRAMEWORK));

	MSG msg;
	::ZeroMemory(&msg, sizeof(MSG));


	XE::XEngine* pEngine =   new XE::XEngine("xEngine.config");
	XE::RenderConfig config(g_hWnd,false,800,600);

	HRESULT hr = \
		XE::XEngine::getSingletonPtr()->InitRender(hInstance,"Xd3d9Render",config);
	if(FAILED(hr))
		return 0;


	{
		XE::xTexturePtr pTexture =XE::xTextureManager::getSingleton().CreateResource("tiger.bmp","tiger.bmp");


		if(pTexture.isNull()==false)
		{
			int width = pTexture->GetWidth();
			int height = pTexture->GetHeight();

			width/=4;
			height/=4;
			XE::xString temanme = pTexture->GetName().substr(0,pTexture->GetName().length()-4);
			pTexture->SaveToDDS(temanme);


			XE::xTerrainManager::getSingleton().LoadTerrainFile(".\\data\\Terrain\\Terrain.terrain");
			XE::XEngine::getSingleton().LoadFile("data\\mesh\\rpet.X");

		}

	}
	//
	
	//		XE::XEngine::getSingleton().LoadFile("data\\mesh\\tiny.x");

	/*
	{



	//	XE::xMeshManager::getSingletonPtr()->CreateResource("test","data\\mesh\\tiny2.x");




	//FILE* file = fopen("data\\Tiny_skin.dds","rb");
	//fseek(file,0,SEEK_END);

	//long size = ftell(file);
	//fseek(file,0,SEEK_SET);
	//char* pBuffer = new char[size+1];
	//ZeroMemory(pBuffer,size+1);
	//long cur = 0; 
	//fread(pBuffer,sizeof(char),size+1,file);



	//XE::xTextureCreateParameter	 texturepar("xtesttext",255,255);
	//XE::xTexture* pTexture = static_cast<XE::xTexture*>( XE::xTextureManager::getSingleton().CreateResource(&texturepar));



	XE::xTexturePtr pSecondTexture = XE::xTextureManager::getSingleton().CreateResource("Tiny_skin.bmp","Tiny_skin.bmp");
	//XE::xShaderCreateParameter shaderCreate("shadertex",XE::Vertex_Shader,"data\\HLSLwithoutEffects.vsh","vs_2_0","Ripple");
	XE::xShaderPtr pShader = XE::xShaderManager::getSingleton().CreateResource("BasicHLSL.fx","BasicHLSL.fx");





	XE::xMeshCreateParameter para("textmesh",1,3);
	WORD offset = 0;
	para.m_Dec.AddVertexElement(0, offset,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0);
	para.m_Dec.AddVertexElement(0, offset,D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0);
	//para.m_Dec.AddVertexElement(0, 16,D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR,1);
	para.m_Dec.AddEndElement();



	XE::xMeshPtr pMesh =XE::xMeshManager::getSingleton().CreateResource(&para);


	DWORD indexsize= pMesh->GetPreIndexSize();
	DWORD vertexsize = pMesh->GetPreVertexSize();

	float* pVBuffer =(float*) pMesh->LockVertexBuffer();
	WORD* pVIBuffer = (WORD*)pMesh->LockIndexBuffer();

	DWORD vertexNum = pMesh->GetVertexNumber();
	DWORD indexNum = pMesh->GetIndexNumber();
	//for(int i = 0;i<vertexNum;++i)
	//{
	*pVBuffer++=0.0f;
	*pVBuffer++=100.0f;
	*pVBuffer++=0.0f;
	//uv
	*pVBuffer++ = 0.0f;
	*pVBuffer++ = 0.0f;

	*pVBuffer++=-100.0f;
	*pVBuffer++=0.0f;
	*pVBuffer++=0.0f;

	*pVBuffer++ = 0.0f;
	*pVBuffer++ = 1.0f;



	*pVBuffer++=100.0f;
	*pVBuffer++=0.0f;
	*pVBuffer++=0.0f;

	*pVBuffer++ = 1.0f;
	*pVBuffer++ = 1.0f;


	//}

	*pVIBuffer++ =0;

	*pVIBuffer++ =2;
	*pVIBuffer++ =1;



	pMesh->UnLoackIndexBuffer();
	pMesh->UnLockVertexBuffer();



	XE::xEnity3DCreateParameter e3dpara("texEnity","textmesh","texMaterial");
	XE::xEntity3D* pE3d = static_cast<XE::xEntity3D*>(\
	XE::XEngine::getSingleton().GetMainSceneManager()->CreateRenderObject(e3dpara));


	XE::xSceneNode* pParentNode = XE::XEngine::getSingleton().GetMainSceneManager()->CreateSceneNode("ParentNode");

	//XE::XEngine::getSingleton().GetMainSceneManager()->CreateSceneNode("testNode",pParentNode)->AttachRenderObject(pSkinEntiy);
	XE::xSceneNode* pTargetNode =  XE::XEngine::getSingleton().GetMainSceneManager()->CreateSceneNode("TargetNode",pParentNode);

	XE::xCamera* pCamera =  XE::XEngine::getSingleton().GetMainSceneManager()->GetCameraByName("MainCamera");
	pCamera->SetParent(pTargetNode);


	//XE::xResourceCreateParameter MaterialParameter("testMaterial");
	XE::xMaterialPtr pMat =XE::xMaterialManager::getSingleton().CreateResource("testMaterial0.xmat","testMaterial0.xmat");
	if(pMat.isNull()==false)
	{

	//   pE3d->SetMaterial(pMat);

	//pMesh->SetSubMeshCount(1);

	pMesh->SetSubMeshMaterial(0,pMat);

	}






	}
	//*/


	//XE::XEngine::getSingletonPtr()->LoadFile("data\\mesh\\tiny.x");

	while(msg.message != WM_QUIT)
	{
		if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}else
		{
			try
			{
				Render();
			}
			catch (...)
			{
				delete XE::XEngine::getSingletonPtr();
				return (int) msg.wParam;
			}

		}
	}//*/
	delete XE::XEngine::getSingletonPtr();


	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_XFRAMEWORK));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_XFRAMEWORK);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{


	RECT rect;
	rect.bottom = 600;
	rect.top = 0;
	rect.left = 0;
	rect.right = 800;
	AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW,false);



	hInst = hInstance; // Store instance handle in our global variable

	g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		0, 0, rect.right, rect.bottom, NULL, NULL, hInstance, NULL);

	if (!g_hWnd)
	{
		return FALSE;
	}



	ShowWindow(g_hWnd, nCmdShow);
	UpdateWindow(g_hWnd);

	return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case	WM_CHAR:
		{

			XE::xSceneNode* pCamera =  XE::XEngine::getSingleton().GetMainSceneManager()->GetCameraByName("MainCamera");
			if(pCamera==NULL)
				break;
			if(wParam=='w')
			{
				pCamera->Translate(XE::xVector3(0.0f,0.0f,10.0f),XE::NA_LOCAL);

			}else if(wParam == 'a')
			{
				pCamera->Translate(XE::xVector3(-01.0f,0.0f,0.0f),XE::NA_LOCAL);
			}else if(wParam=='s')
			{
				pCamera->Translate(XE::xVector3(0.0f,0.0f,-10.0f),XE::NA_LOCAL);
			}else if(wParam=='d')
			{
				pCamera->Translate(XE::xVector3(10.0f,0.0f,0.0f),XE::NA_LOCAL);
			}
			break;

		}

	case WM_LBUTTONDOWN:
		{

			break;
		}
	case WM_LBUTTONUP :
		{
			oldpos.x = 0.0f;
			oldpos.y =0.0f;

		}
	case WM_MOUSEMOVE:
		{

			if(wParam==MK_LBUTTON)
			{
				XE::xSceneNode* TargetNode =  
					XE::XEngine::getSingleton().GetMainSceneManager()->GetSceneNodeByName("TargetNode");

				XE::xCamera* pCamera = XE::XEngine::getSingleton().GetMainSceneManager()->GetCameraByName("MainCamera");

				if(oldpos.x ==0&&oldpos.y==0)
				{
					oldpos.x = GET_X_LPARAM(lParam); 
					oldpos.y = GET_Y_LPARAM(lParam); 
					break;
				}

				float x =  GET_X_LPARAM(lParam) -oldpos.x;
				float y =   GET_Y_LPARAM(lParam) -oldpos.y; 
				oldpos.x =  GET_X_LPARAM(lParam);
				oldpos.y =  GET_Y_LPARAM(lParam);

				pCamera->Rotation(XE::xVector3(0.0f,1.0f,0.0f),-x/500.0f/*,XE::NA_LOCAL*/);



				pCamera->Rotation(XE::xVector3(1.0f,0.0f,0.0f),y/500.0f,XE::NA_LOCAL);


			}
			break;

		}

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
